package com.nulldev.util.data.FastMath;

import java.util.Map;

import com.nulldev.util.data.Arrays.maps.trie.TrieMap;
import com.nulldev.util.data.FastMath.impls.Jafama;
import com.nulldev.util.data.FastMath.impls.LibGDX;
import com.nulldev.util.data.FastMath.impls.Native;
import com.nulldev.util.data.FastMath.impls.Rivens;
import com.nulldev.util.data.FastMath.impls.TaylorMath;

public class FastMath {

	public static enum Modes {
		NATIVE,
		LibGDX_PARTIAL,
		TAYLOR_MATH_PARTIAL,
		RIVENS_PARTIAL,
		JAFAMA,
	}

	private static final Map<Modes, Math> cache = new TrieMap<Modes, Math>();
	static {
		if (cache.isEmpty()) {
			cache.put(Modes.NATIVE, Native.INSTANCE);
			cache.put(Modes.LibGDX_PARTIAL, LibGDX.INSTANCE);
			cache.put(Modes.TAYLOR_MATH_PARTIAL, TaylorMath.INSTANCE);
			cache.put(Modes.RIVENS_PARTIAL, Rivens.INSTANCE);
			cache.put(Modes.JAFAMA, Jafama.INSTANCE);
		}
	}

	public static final Modes DEFAULT_MODE = Modes.JAFAMA;
	public static final Math DEFAULT_INSTANCE = get();

	public static Math get() {
		return get(DEFAULT_MODE);
	}

	public static Math get(final Modes mode) {
		if (mode == null) {
			return cache.get(Modes.JAFAMA);
		}
		return cache.getOrDefault(mode, cache.get(Modes.NATIVE));
	}

	@SuppressWarnings("static-access")
	public static double cos(double phi) {
		return DEFAULT_INSTANCE.cos(phi);
	}

	@SuppressWarnings("static-access")
	public static double cbrt(double d) {
		return DEFAULT_INSTANCE.cbrt(d);
	}

	@SuppressWarnings("static-access")
	public static double acos(double d) {
		return DEFAULT_INSTANCE.acos(d);
	}
}
